//语音识别模块
#include <string.h>
#include <rtthread.h>
#include <rtconfig.h>
#include <aic_core.h>
#include "pm20_app_voice.h"
#include "pm20_drv_uart3.h"
// #include "pm20_app_board.h"
#include <rtdevice.h>
extern  size_t voi_recv_buff_len;                   // 当前缓冲区中的数据长度
#define VOI_RECV_BUFF_LEN 8  // 增加缓冲区大小
extern  uint8_t voi_recv_buff[VOI_RECV_BUFF_LEN];   // 接收数据缓冲区
#define on  1
#define off 0
int switch_auto;
int switch_comfort;
int switch_strong;
// int switch_heating;
// int switch_humidifier;
// int switch_plasma;
int set_time;
int switch_time;
int cartridge_life_data;
int air_quality_data;
int temperature_data;
int humidity_data;

// 校验和计算函数，包括从长度字段开始到校验和字段之前的所有字节
uint8_t calculate_checksum(const uint8_t *data, uint8_t length) 
{
    uint8_t sum = 0;
    for (int i = 1; i < length; ++i) 
    { 
        // 从frame[1]开始，直到frame[length-1]
        sum += data[i];
    }
    return sum;
}
// 释放数据字段的内存
void free_frame_data(FrameDataParams *params) {
    if (params && params->data) {
        free(params->data);
        params->data = NULL;// 将指针设置为NULL，防止野指针
    }
}
/********************************************************************************************** */
// 接收接口函数
// 滤芯寿命读取接收(滤芯寿命剩余 10 - 100%)
int Cartridge_Life_data(int data)
{
    cartridge_life_data = data;
    return cartridge_life_data;
}
int rev_filter_life_remaining()
{
    // 读取滤芯寿命数值 data 操作
    int data = cartridge_life_data;
    uint8_t command = REV_FILTER_LIFE_REMAINING[data % 10];
    return command;
}
// 空气质量读取接收(0-优 1-良 2-较差 3-差)
int Air_Quality_data(int data)
{
    air_quality_data = data;
    return air_quality_data;
}
int rev_atr_quality()
{
    // 读取空气质量等级数值 data 操作
    int data = air_quality_data;
    uint8_t command = REV_AIR_QUALITY[data];
    return command;
}
// 温度数据读取接收(0 - 41)
int Temperature_data(int data)
{
    temperature_data = data;
    return temperature_data;
}
int rev_temperature()
{
    // 读取温度数值 data 操作
    int data = temperature_data;
    uint8_t command = REV_TEMPERATURE[data];
    return command;
}
// 湿度数据读取接收(10 - 100%)
int Humidity_data(int data)
{
    humidity_data = data;
    return humidity_data;
}
int rev_humidity()
{
    // 读取湿度数值 data 操作
    int data = humidity_data;
    uint8_t command = REV_HUMIDIFIER[(data-10) % 10];
    return command;
}
/********************************************************************************************** */
int voi_switch_auto(void)
{
    return switch_auto;
}// 开自动模式   等于1开启
int voi_switch_comfort(void)
{
    return switch_comfort;
}// 开舒适模式   等于1开启
int voi_switch_strong(void)
{
    return switch_strong;
}// 开强劲模式   等于1开启
int voi_switch_time(void)
{
    return switch_time;
}// 定时关闭     等于0关闭

// 开关净化器操作 1 开 0 关
int turn_on_off_purifier(void) {
    return 0x03;
}
// 开关加热  1 开 0 关
int turn_on_off_heating(int state) {
    if (state == 1) {
        return 0x1B;
    } else{
        return 0x1C;
    }
}
// 开关等离子  1 开 0 关
int turn_on_off_plasma(int state) {
    if (state == 1) {
        return 0x54;
    } else{
        return 0x53;
    }
}
// // 垂直风向挡位调节
// int wind_vertical_direction(uint8_t command)
// {
//     send_frame.swing_setting = WIND_VERTICAL_DIRECTION[command - 0x04];
//     return command + 0x01;
// }
// 水平风向挡位调节
int wind_level_direction(uint8_t command)
{
    switch (command)
    {
    case 0x08:
        send_frame.swing_setting = WIND_LEVEL_DIRECTION[0];
        break;
    case 0x09:
        send_frame.swing_setting = WIND_LEVEL_DIRECTION[1];
        break;
    case 0x0B:
        send_frame.swing_setting = WIND_LEVEL_DIRECTION[2];
        break;
    case 0x0D:
        send_frame.swing_setting = WIND_LEVEL_DIRECTION[3];
        break;
    default:
        break;
    }
    return command;
}
// 风速挡位调节
int wind_speed(uint8_t command)
{
    send_frame.fan_speed_pos = WIND_SPEED[command - 0x0E];
    return command;
}
// 温度挡位调节
int temperature_adjustment(uint8_t command)
{
    send_frame.electrical_heating = TEMPERATURE_ADJUSTMENT[command - 0x1D];
    return command;
}
// 定时挡位调节
int time_adjustment(uint8_t command)
{
    set_time = TIMING[command - 0x47];
    return command;
}
// 执行命令
uint8_t execute_command_voi(uint8_t command) 
{
    uint8_t result = 0x00;
    if (command >= 0x0E && command <= 0x17)
    {
        result = wind_speed(command);
    }
    else if (command >= 0x1D && command <= 0x45)
    {
        result = temperature_adjustment(command);
    }
    else if (command >= 0x47 && command <= 0x52)
    {
        result = time_adjustment(command);
    }
    // else if (command >= 0x04 && command < 0x08)
    // {
    //     result = wind_vertical_direction(command);
    // }
    else if (command >= 0x08 && command < 0x0E)
    {
        result = wind_level_direction(command);
    }
    switch (command) 
    {
        case CMD_WAKE_WORD:
            result = 0x01;
            break;
        case CMD_TURN_ON_OFF_AIR_PURIFIER:
            send_frame.power_on_command = off;
            result = turn_on_off_purifier();
            break;
        case CMD_TURN_ON_OFF_AIR_PURIFIER + 0x01:
            send_frame.power_on_command = on;
            result = turn_on_off_purifier();
            break;
        case CMD_TURN_ON_OFF_AUTO_MODE:
            switch_auto = on;
            result = 0x18;
            break;
        case CMD_TURN_ON_OFF_COMFORT_MODE:
            switch_comfort = on;
            result = 0x19;
            break;
        case CMD_TURN_ON_OFF_STRONG_MODE:
            switch_strong = on;
            result = 0x1A;
            break;
        case CMD_TURN_ON_OFF_HEATING:
            send_frame.electric_heating_command = on;
            result = turn_on_off_heating(on);
            break;
        case CMD_TURN_ON_OFF_HEATING + 0x01:
            send_frame.electric_heating_command = off;
            result = turn_on_off_heating(off);
            break;
        case CMD_TURN_ON_OFF_PLASMA + 0x01:
            send_frame.ion_command = on;
            result = turn_on_off_plasma(on);
            break;
        case CMD_TURN_ON_OFF_PLASMA:
            send_frame.ion_command = off;
            result = turn_on_off_plasma(off);
            break;
        case CMD_OFF_TIMING:
            switch_time = off;
            result = 0x46;
        case CMD_YES_TURN_ON_STRONG_MODE:
            switch_strong = on;
            result = 0x1A;
            break;
        case CMD_CAN_TURN_ON_STRONG_MODE:
            switch_strong = on;
            result = 0x1A;
            break;
        case CMD_NOT_NEEDED:
            result = 0x03;
            break;
        case CMD_FILTER_LIFE_REMAINING:
            result = rev_filter_life_remaining();
            break;
        case CMD_AIR_QUALITY:
            result = rev_atr_quality();
            break;
        case CMD_WHAT_IS_THE_TEMPERATURE:
            result = rev_temperature();
            break;
        case CMD_WHAT_IS_THE_HUMIDITY:
            result = rev_humidity();
            break;
        default:
            printf("Unknown command: %02X\n", command);
            break;
    }
    return result;
}
/*====================================================发送到语音模块的数据===========================================*/
// 构建语音命令帧
uint8_t* build_frame( uint8_t data ) 
{
    // 帧长度 = 命令头(1字节) + 长度(1字节) + 命令字(3字节) + 命令(2字节) + 校验(1字节) + 结束码(1字节) = 9字节
    size_t frame_length = DATA_LENGTH2 + 2;
    uint8_t *frame = (uint8_t *)malloc(frame_length);
    if (!frame) 
    {
        return NULL;
    }

    // 填充帧头
    frame[0] = FRAME_HEAD;
    frame[1] = DATA_LENGTH2;
    frame[2] = FRAME_COM1;
    frame[3] = FRAME_COM2;
    frame[4] = FRAME_COM3;
    frame[5] = VOICE_COM2;
    // frame[6] = (data == 0x01) ? 0x01 : data + 0x01;
    frame[6] = data;
    frame[8] = FRAME_END;
    // 计算校验和
    uint8_t checksum = calculate_checksum(frame, DATA_LENGTH2);
    // 填充校验和
    frame[7] = checksum;
    return frame;
}

//执行相应语音操作，操作完成后返回语音指令
void testAnalysisData(uint8_t data) 
{
    //根据 data 执行操作
    uint8_t result = execute_command_voi(data);
    // 构建数据帧
    uint8_t *frame = build_frame(result);
    if (frame) 
    {
        // 发送数据帧
        voi_send_data(frame);
        free(frame);
    }
}
/*====================================================解析语音模块发送的数据===========================================*/

// 解析接收到的数据帧
int parse_voice_command(const uint8_t *frame, uint16_t frame_length, FrameDataParams *params) 
{
    if (frame == NULL || frame_length < 8 || params == NULL) 
    {
        return -1; // 无效参数或帧长度不足
    }
    // 检查帧头和结束码
    if (frame[0] != FRAME_HEAD || frame[frame_length - 1] != FRAME_END) 
    {
        return -2; // 帧头或结束码不匹配
    }
    uint8_t length = frame[1]; // 获取长度字段的值
    if (length + 2 != frame_length) 
    {   // 长度校验，包括校验和和结束码
        return -3; // 数据帧长度不匹配
    }
    // 计算校验和
    uint8_t calculated_checksum = calculate_checksum(frame, length);
    if (calculated_checksum != frame[length]) 
    {   // 校验和比较
        return -4; // 校验和不匹配
    }
    // 命令字检查，示例中命令字为0xFF 0x06
    if (frame[2] != FRAME_COM1 || frame[3] != FRAME_COM2) 
    {
        return -5; // 命令字不匹配
    }
    // 复制数据字段到params
    params->data_length = length - 4; // 实际命令长度，不包括命令头+长度+命令字
    params->data = (uint8_t *)malloc(params->data_length);
    if (params->data == NULL) 
    {
        return -6; // 内存分配失败
    }
    memcpy(params->data, frame + 4, params->data_length);
    return 0; // 解析成功
}

// 处理接收到的数据字段
void Process_Rev_data(FrameDataParams *params) 
{
    if (params == NULL || params->data == NULL) 
    {
        printf("Error: Invalid parameters or data is NULL.\n");
        return; // 无效参数
    }
    // 由于命令只有两个字节，我们可以直接检查params->data
    if (params->data_length == 2) 
    {
        // 检查是否是预期的命令
        if (params->data[0] == 0x01) 
        {
            testAnalysisData(params->data[1]);
        }
    }
}

/*====================================================解析语音模块发送的数据完毕===========================================*/

static void pm_app_voice_callback(void *parameter)
{
    while(1)
    {                
        const uint8_t *frame_data = process_received_voi_data();
        uint16_t frame_length = get_voi_recv_buff_len(); // 使用接收到的实际数据长度
        if (frame_length == 8) 
        {
            FrameDataParams *params;
            if (parse_voice_command(frame_data, frame_length, &params) == 0)
            {
                Process_Rev_data(&params);
                free_frame_data(&params);
            } 
            else
            {
                free_frame_data(&params);
            }
        }
        voi_recv_buff_len = 0;
        rt_thread_mdelay(200);
    }
}
void pm20_app_voice_init(void)
{
    rt_thread_t voice = rt_thread_create("voice", pm_app_voice_callback, RT_NULL, 1024*4, 25, 10);
    if(voice != RT_NULL)
    {
        rt_thread_startup(voice);
    }
    else
    {
        rt_kprintf("err\n");
    }
}